package parser;

import java.io.*;
import java.util.*;

public class CellParser {

	public static void main(String[] args) {
		
		String inputPath = "C:\\Users\\Axel\\Documents\\Thesis\\Data" +
						   "\\130312-MG1655_stat_crop_xy1\\130312_pos1_raw.csv";
		List<Integer> lin1 = new ArrayList<Integer>();
		List<Integer> lin2 = new ArrayList<Integer>();
		List<Integer> lin3 = new ArrayList<Integer>();
		List<Integer> lin4 = new ArrayList<Integer>();
		List<Integer> lin5 = new ArrayList<Integer>();
		List<Integer> cells = new ArrayList<Integer>();
		int lineageID = 0;
		String path = createPath(inputPath);
		String experimentID = "1";
		
		try {
		System.out.println(":: Start analyzing: " + displayFileName(inputPath));
		
		/* Readers and writers */	
		BufferedReader read = new BufferedReader(new InputStreamReader
				(new FileInputStream(inputPath)));
		System.out.println(":: Creating file: lineage.csv");
		PrintWriter lincsv = new PrintWriter(new FileOutputStream(path + "lineage.csv"));
		System.out.println(":: Creating file: cell.csv");
		PrintWriter intermedcsv = new PrintWriter(new FileOutputStream(path + "intermed.csv"));
		System.out.println(":: Creating file: stateOverTime.csv");
		PrintWriter sotcsv = new PrintWriter(new FileOutputStream(path + "stateOverTime.csv"));
		System.out.println(":: Creating file: fluorescence.csv");
		PrintWriter fluocsv = new PrintWriter(new FileOutputStream(path + "fluorescence.csv"));
		
		/* Write title to files*/
		lincsv.println("Id;experimentId");
		intermedcsv.println("Id;LineageId;ParentId;Pole;BirthTime");
		sotcsv.println("Id;CellId;Time;Width;Length;Curvature;Perimeter;Area;Volume" + 
						";Growthspeed");
		fluocsv.println("Id;StateId;XCoord;YCoord;Width;Height;Area;Intensity");
		String line = read.readLine();
		System.out.println(":: Start filling all files with data");
		line = read.readLine();
		/*  Start reading file and writing to appropriate file*/
		while (line != null) { 
			String[] cellInfo = line.split(";");
			int ID = Integer.parseInt(cellInfo[0]);
			int frameNr = Integer.parseInt(cellInfo[1]);
			int cellID = Integer.parseInt(cellInfo[2]);
			int parentID = Integer.parseInt(cellInfo[3]);
			int polarity = Integer.parseInt(cellInfo[4]);
			double cellLength = Double.parseDouble(cellInfo[5].replace(",",	".")) * 
								getResolution();
			double cellWidth = Double.parseDouble(cellInfo[6].replace(",",".")) * 
							   getResolution();
			double cellArea = Double.parseDouble(cellInfo[7].replace(",",".")) * 
							  Math.pow(getResolution(), 2);
			double cellVolume = Double.parseDouble(cellInfo[8].replace(",",".")) *
								Math.pow(getResolution(), 3);
			
			// Check for lineageID
			if (frameNr == 1) {
				if (cellID == 1) {
					lineageID = 1;
					lin1.add(1);
					birthDays.put(1, formatMinutes(frameNr-1));
					lincsv.println(lineageID + ";" + experimentID);
				}
				if (cellID == 2) {
					lineageID = 2;
					lin2.add(2);
					birthDays.put(2, formatMinutes(frameNr-1));
					lincsv.println(lineageID + ";" + experimentID);
				}
				if (cellID == 3) {
					lineageID = 3;
					lin3.add(3);
					birthDays.put(3, formatMinutes(frameNr-1));
					lincsv.println(lineageID + ";" + experimentID);
				}
				if (cellID == 4) {
					lineageID = 4;
					lin4.add(4);
					birthDays.put(4, formatMinutes(frameNr-1));
					lincsv.println(lineageID + ";" + experimentID);
				}
				if (cellID == 5) {
					lineageID = 5;
					lin5.add(5);
					birthDays.put(5, formatMinutes(frameNr-1));
					lincsv.println(lineageID + ";" + experimentID);
				}
			}
			else {
				if (parentID == 0) {
					lineageID = cellID;
				}
				else {
					if (birthDays.containsKey(cellID)) {
						if (lin1.contains(cellID)){
							lineageID = 1;
						}
						else if (lin2.contains(cellID)){
							lineageID = 2;
						}
						else if (lin3.contains(cellID)){
							lineageID = 3;
						}
						else if (lin4.contains(cellID)){
							lineageID = 4;
						}
						else {
							lineageID = 5;
						}
					}
					else {
						birthDays.put(cellID, formatMinutes(frameNr-1));
						if (lin1.contains(parentID)){
							lineageID = 1;
							lin1.add(cellID);
						}
						else if (lin2.contains(parentID)){
							lineageID = 2;
							lin2.add(cellID);
						}
						else if (lin3.contains(parentID)){
							lineageID = 3;
							lin3.add(cellID);
						}
						else if (lin4.contains(parentID)){
							lineageID = 4;
							lin4.add(cellID);
						}
						else {
							lineageID = 5;
							lin5.add(cellID);
						}						
					}
				}
			}
			String birthframe = birthDays.get(cellID);
			String time = formatMinutes(frameNr-1); 
			
			if (! cells.contains(cellID)){
				intermedcsv.println(cellID + ";" + lineageID + ";" + parentID + ";" + polarity + 
								";" + birthframe);
				cells.add(cellID);
				/* Add unique parents to the parents Map */
				if (parentID != 0 && cellID %2 == 0 ) {
					parents.put(parentID, cellID);
				}
			}
			sotcsv.println(ID + ";" + cellID + ";" +  time + ";" + cellLength + ";" + 
							cellWidth + ";;;" + cellArea + ";" + cellVolume + ";");
			fluocsv.println(ID + ";;;;;;;");
			line = read.readLine();
		}
		
		/* Close all read and write streams */
		System.out.println(":: Closing all streams");
		read.close();
		lincsv.close();
		intermedcsv.close();
		sotcsv.close();
		fluocsv.close();
		
		BufferedReader read2 = new BufferedReader(new InputStreamReader
				(new FileInputStream(path + "intermed.csv")));
		PrintWriter cellcsv = new PrintWriter(new FileOutputStream(path + "cell.csv"));
		cellcsv.println("Id;LineageId;ParentId;Pole;BirthTime:DivisionTime;DeathTime" +
						";LagTime;PictureXCoord;PictureYCoord");
		String line2 = read2.readLine();
		line2 = read2.readLine();
		String divTime = "";
		int ds = 0;
		while (line2 != null) { 
			String[] intermediateInfo = line2.split(";");
			int id2 = Integer.parseInt(intermediateInfo[0]);
			int lineageID2 = Integer.parseInt(intermediateInfo[1]);
			int parentID2 = Integer.parseInt(intermediateInfo[2]);
			int pole2 = Integer.parseInt(intermediateInfo[3]);
			String birth2 = intermediateInfo[4];
			if  (parents.containsKey(id2)){
					ds = parents.get(id2);
					divTime = birthDays.get(ds);
			}
			else {
				divTime = "";
			}
			cellcsv.println(id2 + ";" + lineageID2 + ";" + parentID2 + ";" + lineageID + ";" 
							+ pole2 + ";" + birth2 + ";" + divTime + ";;;");
			line2 = read2.readLine();
		}
		cellcsv.close();
		read2.close();
		String rm1 = "cmd /c del " + path + "intermed.csv";
		Runtime.getRuntime().exec(rm1);
		}
		catch (Exception e) {
			e.printStackTrace();			
		}
	}
	
	/**
	 * Returns the file name
	 * @param path 
	 * @return
	 */
	public static String displayFileName(String path) {
		int i1 = path.lastIndexOf("\\");
		return path.substring(i1+1);
	}
	
	/**
	 * Returns the path to the correct experiment folder
	 * @param	path
	 * 			inputpath		
	 * @return
	 */
	public static String createPath(String path) {
		int i1 = path.lastIndexOf("\\");
		return path.substring(0,i1) + "\\";
	}
	
	/**
	 * Converts minutes to the 00:00:00 format
	 * @param t Number of minutes
	 * @return	formatted String
	 */
	public static String formatMinutes(int t) {
		int hours = t / 60;
		int minutes = t % 60;
		return String.format("%02d:%02d:%s",hours,minutes,"00");
	}
	
	/**
	 * Returns the time interval
	 * @return
	 */
	public static int getTimeInterval() {
		return TIME_INTERVAL;
	}
	
	/**
	 * Returns the resolution
	 * @return
	 */
	public static double getResolution() {
		return RESOLUTION;
	}
	
	/**
	 * Time interval for time-lapse movies
	 */
	private final static int TIME_INTERVAL = 1;
	
	/**
	 * Resolution of the time-lapse movies
	 */
	private final static double RESOLUTION = 0.073;
	
	/**
	 * This map contains the cell ID and the time of first appearance,
	 * time is formatted conform the 00:00:00 format.
	 */
	private static final Map<Integer,String> birthDays = new HashMap<Integer,String>();
	
	/**
	 * Contains cellID and parentID
	 */
	private static final Map<Integer,Integer> parents = new HashMap<Integer,Integer>();
}
